package com.ls.uav_backend.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.ls.uav_backend.exception.BusinessException;
import com.ls.uav_backend.exception.ErrorCode;
import com.ls.uav_backend.manger.OneNetResourceManger;
import com.ls.uav_backend.manger.WeatherManger;
import com.ls.uav_backend.mapper.EnvironmentalDataMapper;
import com.ls.uav_backend.model.entity.EnvironmentalData;
import com.ls.uav_backend.model.entity.SensorData;
import com.ls.uav_backend.model.enums.SensorTypeEnum;
import com.ls.uav_backend.model.vo.*;
import com.ls.uav_backend.model.vo.environmental.*;
import com.ls.uav_backend.service.EnvironmentalDataService;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 *  服务层实现。
 *
 * @author <a href="https://gitee.com/Linkating">LinSkating</a>
 */

@Service
public class EnvironmentalDataServiceImpl extends ServiceImpl<EnvironmentalDataMapper, EnvironmentalData> implements EnvironmentalDataService {

    @Resource
    private WeatherManger weatherManger;

    @Resource
    private OneNetResourceManger oneNetResourceManger;

    // 缓存数据
    private static final Map<String, Object> DATA_CACHE = new HashMap<>();
    private static final String DATE_KEY = "dateKey";
    private static final String DATA_KEY = "dataKey";

    // 定义日期格式
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd HH:mm:ss");

    @Override
    public InAndOutTemperatureVO getInAndOutTemperatureData() {
        List<EnvironmentalData> environmentalDataList = (List<EnvironmentalData>) DATA_CACHE.get(DATA_KEY);
        if (ObjUtil.isEmpty(environmentalDataList)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "数据暂时获取失败");
        }
        List<BigDecimal> indoorTemperatureList = new ArrayList<>();
        List<BigDecimal> outdoorTemperatureList = new ArrayList<>();
        List<String> dataTimestampList = new ArrayList<>();
        for (EnvironmentalData environmentalData : environmentalDataList) {
            indoorTemperatureList.add(environmentalData.getIndoorTemperature());
            outdoorTemperatureList.add(environmentalData.getOutdoorTemperature());
            // 格式化日期并添加到列表
            LocalDateTime timestamp = environmentalData.getDataTimestamp();
            if (timestamp != null) {
                dataTimestampList.add(timestamp.format(formatter));
            } else {
                dataTimestampList.add(null); // 处理可能的 null 值
            }
        }
        return new InAndOutTemperatureVO(indoorTemperatureList, outdoorTemperatureList, dataTimestampList);
    }

    @Override
    public IlluminationVO getIlluminationData() {
        List<EnvironmentalData> environmentalDataList = (List<EnvironmentalData>) DATA_CACHE.get(DATA_KEY);
        if (ObjUtil.isEmpty(environmentalDataList)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "数据暂时获取失败");
        }
        List<BigDecimal> illuminationList = new ArrayList<>();
        List<String> dataTimestampList = new ArrayList<>();
        for (EnvironmentalData environmentalData : environmentalDataList) {
            illuminationList.add(environmentalData.getIllumination());
            // 格式化日期并添加到列表
            LocalDateTime timestamp = environmentalData.getDataTimestamp();
            if (timestamp != null) {
                dataTimestampList.add(timestamp.format(formatter));
            } else {
                dataTimestampList.add(null); // 处理可能的 null 值
            }
        }
        return new IlluminationVO(illuminationList, dataTimestampList);
    }

    @Override
    public WaterContentVO getWaterContentData() {
        List<EnvironmentalData> environmentalDataList = (List<EnvironmentalData>) DATA_CACHE.get(DATA_KEY);
        if (ObjUtil.isEmpty(environmentalDataList)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "数据暂时获取失败");
        }
        List<BigDecimal> waterContentList = new ArrayList<>();
        List<String> dataTimestampList = new ArrayList<>();
        for (EnvironmentalData environmentalData : environmentalDataList) {
            waterContentList.add(environmentalData.getMoisture());
            // 格式化日期并添加到列表
            LocalDateTime timestamp = environmentalData.getDataTimestamp();
            if (timestamp != null) {
                dataTimestampList.add(timestamp.format(formatter));
            } else {
                dataTimestampList.add(null); // 处理可能的 null 值
            }
        }
        return new WaterContentVO(waterContentList, dataTimestampList);
    }

    @Override
    public SoilVO getSoilData() {
        List<EnvironmentalData> environmentalDataList = (List<EnvironmentalData>) DATA_CACHE.get(DATA_KEY);
        if (ObjUtil.isEmpty(environmentalDataList)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "数据暂时获取失败");
        }
        List<BigDecimal> soilFertilizerConcentrationList = new ArrayList<>();
        List<BigDecimal> soilPhList = new ArrayList<>();
        List<String> dataTimestampList = new ArrayList<>();
        for (EnvironmentalData environmentalData : environmentalDataList) {
            soilFertilizerConcentrationList.add(environmentalData.getSoilFertilizerConcentration());
            soilPhList.add(environmentalData.getSoilPh());
            // 格式化日期并添加到列表
            LocalDateTime timestamp = environmentalData.getDataTimestamp();
            if (timestamp != null) {
                dataTimestampList.add(timestamp.format(formatter));
            } else {
                dataTimestampList.add(null); // 处理可能的 null 值
            }
        }
        return new SoilVO(soilFertilizerConcentrationList, soilPhList, dataTimestampList);
    }

    @Override
    public SensorDataVO getSensorData() {
        List<EnvironmentalData> environmentalDataList = (List<EnvironmentalData>) DATA_CACHE.get(DATA_KEY);
        if (ObjUtil.isEmpty(environmentalDataList)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "数据暂时获取失败");
        }
        SensorDataVO sensorDataVO = new SensorDataVO();
        for (EnvironmentalData environmentalData : environmentalDataList) {
            if (environmentalData.getConductivity() > 0) {
                sensorDataVO.setConductivity(environmentalData.getConductivity());
                sensorDataVO.setPotassium(environmentalData.getPotassium());
                sensorDataVO.setNitrogen(environmentalData.getNitrogen());
                sensorDataVO.setPhosphorus(environmentalData.getPhosphorus());
                break;
            }
        }
        return sensorDataVO;
    }

    // 获取过去24H的环境记录数据，并保存在map中，减轻数据库压力
    @Override
    public void get24HEnvironmentalData() {
        // 计算24小时前的时间点
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR_OF_DAY, -24);
        Date startTime = calendar.getTime();
        Date endTime = new Date(); // 当前时间
        // 查询数据
        QueryWrapper queryWrapper = this.queryChain()
                .between(EnvironmentalData::getDataTimestamp, startTime, endTime) // 修正时间范围
                .orderBy(EnvironmentalData::getDataTimestamp, Boolean.TRUE)
                .toQueryWrapper();// 按时间升序排序
        List<EnvironmentalData> list = this.list(queryWrapper);
        if (ObjUtil.isEmpty(list)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "24小时内的数据为空");
        }
        // 缓存
        DATA_CACHE.put(DATE_KEY, new Date());
        DATA_CACHE.put(DATA_KEY, list);
    }

    // 更新当前大棚总信息
    @Override
    public void updateCurrentEnvironmentalData() {
        EnvironmentalData environmentalData = new EnvironmentalData();
        AmapWeatherResponse currentWeather = weatherManger.getCurrentWeather();
        BigDecimal outdoorTemperature = new BigDecimal(0);
        if (currentWeather != null) {
            List<AmapWeatherResponse.LiveWeather> weatherLives = currentWeather.getLives();
            if (weatherLives != null && !weatherLives.isEmpty()) {
                outdoorTemperature = new BigDecimal(weatherLives.getFirst().getTemperature());
            }
        }
        // 获取传感器数据
        String oneNetResource = oneNetResourceManger.getOneNetResource();
        System.out.println(oneNetResource);
        JSONArray jsonArray = JSONUtil.parseArray(oneNetResource);
        Map<String, List<SensorData>> res = jsonArray.toList(SensorData.class).stream().collect(Collectors.groupingBy(SensorData::getName));
        // 时间戳
        environmentalData.setDataTimestamp(LocalDateTime.now());
        // 室内温度
        String indoorTemperature = res.get(SensorTypeEnum.INDOOR_TEMPERATURE.getText()).getFirst().getValue();
        environmentalData.setIndoorTemperature(new BigDecimal(indoorTemperature));
        // 室外温度
        environmentalData.setOutdoorTemperature(outdoorTemperature);
        // 水分
        String moisture = res.get(SensorTypeEnum.MOISTURE.getText()).getFirst().getValue();
        environmentalData.setMoisture(new BigDecimal(moisture));
        // 氮
        int nitrogen = Integer.parseInt(res.get(SensorTypeEnum.NITROGEN.getText()).getFirst().getValue());
        environmentalData.setNitrogen(nitrogen);
        // 磷
        int phosphorus = Integer.parseInt(res.get(SensorTypeEnum.PHOSPHORUS.getText()).getFirst().getValue());
        environmentalData.setPhosphorus(phosphorus);
        // 钾
        int potassium = Integer.parseInt(res.get(SensorTypeEnum.POTASSIUM.getText()).getFirst().getValue()) ;
        environmentalData.setPotassium(potassium);
        // 肥料浓度
        environmentalData.setSoilFertilizerConcentration(BigDecimal.valueOf(nitrogen + phosphorus + potassium));
        // 土壤PH
        String ph = res.get(SensorTypeEnum.PH.getText()).getFirst().getValue();
        environmentalData.setSoilPh(new BigDecimal(ph));
        // 电导率
        int conductivity = Integer.parseInt(res.get(SensorTypeEnum.CONDUCTIVITY.getText()).getFirst().getValue());
        environmentalData.setConductivity(conductivity);
        // TODO 光照强度
        environmentalData.setIllumination(BigDecimal.ZERO);
        this.save(environmentalData);
    }

}
